import 'dart:async';

import 'package:flutter/widgets.dart';
import 'package:learning_content_admin_pannel.core/core/presentation/widgets/stateful_wloc.dart';

class WlocBuilder<W extends StatefulWloc<S, dynamic>, S> extends ConverterWlocBuilder<W, S, S> {
  const WlocBuilder({
    required super.wloc,
    required super.builder,
    super.buildWhen,
    super.key,
  }) : super(converter: _identity);

  static S _identity<S>(S state) => state;
}

class ConverterWlocBuilder<W extends StatefulWloc<S, dynamic>, S, VM> extends StatefulWidget {
  const ConverterWlocBuilder({
    required this.wloc,
    required this.converter,
    required this.builder,
    this.buildWhen,
    super.key,
  });

  final W wloc;
  final VM Function(S state) converter;
  final Widget Function(BuildContext context, VM state) builder;
  final bool Function(VM previous, VM current)? buildWhen;

  @override
  State<ConverterWlocBuilder<W, S, VM>> createState() => _ConverterWlocBuilderState<W, S, VM>();
}

class _ConverterWlocBuilderState<W extends StatefulWloc<S, dynamic>, S, VM>
    extends State<ConverterWlocBuilder<W, S, VM>> {
  late Stream<VM> _stream;

  Stream<VM> _createStream() {
    return widget.wloc.stream.map(widget.converter).distinct((previous, current) {
      if (widget.buildWhen != null) {
        return !widget.buildWhen!(previous, current);
      }

      return current == previous;
    });
  }

  @override
  void initState() {
    super.initState();
    _stream = _createStream();
  }

  @override
  void didUpdateWidget(ConverterWlocBuilder<W, S, VM> oldWidget) {
    super.didUpdateWidget(oldWidget);

    if (oldWidget.wloc.stream != widget.wloc.stream) {
      _stream = _createStream();
    }
  }

  @override
  Widget build(BuildContext context) {
    return StreamBuilder<VM>(
      initialData: widget.converter(widget.wloc.state),
      stream: _stream,
      builder: (context, snapshot) {
        return widget.builder(context, snapshot.data as VM);
      },
    );
  }
}

// class _ConverterWlocBuilderState<W extends StatefulWloc<S, dynamic>, S, VM>
//     extends State<ConverterWlocBuilder<W, S, VM>> {
//   StreamSubscription<VM>? _subscription;
//   late VM _state;
//
//   void _subscribe() {
//     final stream = widget.wloc.stream.map(widget.converter).distinct((previous, current) {
//       if (widget.buildWhen != null) {
//         return !widget.buildWhen!(previous, current);
//       }
//
//       return current == previous;
//     });
//
//     _subscription = stream.listen((VM state) {
//       setState(() {
//         _state = state;
//       });
//     });
//   }
//
//   void _unsubscribe() {
//     if (_subscription != null) {
//       _subscription!.cancel();
//       _subscription = null;
//     }
//   }
//
//   @override
//   void initState() {
//     super.initState();
//     _subscribe();
//     _state = widget.converter(widget.wloc.state);
//   }
//
//   @override
//   void didUpdateWidget(ConverterWlocBuilder<W, S, VM> oldWidget) {
//     super.didUpdateWidget(oldWidget);
//
//     if (oldWidget.wloc.stream != widget.wloc.stream) {
//       _unsubscribe();
//       _subscribe();
//       _state = widget.converter(widget.wloc.state);
//     }
//   }
//
//   @override
//   void dispose() {
//     _unsubscribe();
//     super.dispose();
//   }
//
//   @override
//   Widget build(BuildContext context) => widget.builder(context, _state);
// }

// class ConverterWlocBuilder<W extends StatefulWloc<S, dynamic>, S, VM> extends StatelessWidget {
//   const ConverterWlocBuilder({
//     required this.wloc,
//     required this.converter,
//     required this.builder,
//     this.buildWhen,
//     super.key,
//   });
//
//   final W wloc;
//   final VM Function(S state) converter;
//   final Widget Function(BuildContext context, VM state) builder;
//   final bool Function(VM previous, VM current)? buildWhen;
//
//   Stream<VM> get _stream {
//     return wloc.stream.map(converter).distinct((previous, current) {
//       if (buildWhen != null) {
//         return !buildWhen!(previous, current);
//       }
//
//       return current == previous;
//     });
//   }
//
//   @override
//   Widget build(BuildContext context) {
//     return StreamBuilder<VM>(
//       initialData: converter(wloc.state),
//       stream: _stream,
//       builder: (context, snapshot) {
//         return builder(context, snapshot.data as VM);
//       },
//     );
//   }
// }
